package cn.nawang.ebeim.client.version;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.nawang.ebeim.client.bean.DataSource;
import cn.nawang.ebeim.client.bean.LocalBackupQueue;
import cn.nawang.ebeim.client.bean.LocalBackupTask;
import cn.nawang.ebeim.client.util.Constants;
import cn.nawang.ebeim.client.util.FileUtil;
import cn.nawang.ebeim.client.util.TransportUtil;
import cn.nawang.ebeim.client.util.VersionTreeSerializerFactory;
import cn.nawang.ebeim.client.util.ZipUtil;

public class VersionTreeUtil {
  private static final Logger LOG = LoggerFactory.getLogger(VersionTreeUtil.class);

  public static VersionTree generateVersionTree(DataSource ds) throws IOException {
    LOG.debug("generate version for {}", ds);
    File file = new File(ds.getRoot());
    if (!file.exists()) {
      return null;
    }
    VersionTree vt = new VersionTree();
    scan(file, vt.getRoot(),ds);
    return vt;
  }

  public static void scan(File file, DirectoryNode parentNode,DataSource ds){
    //设置根目录id
    if(parentNode.getParent()==null && parentNode.getName().equals("/")){
      parentNode.setNid(UUID.randomUUID().toString());
    }
    if (file.isDirectory()) {
      File[] files = file.listFiles();
      if(files == null){
        //在测试C:\Program Files为数据源时，发现C:\Program Files\Windows NT\附件找不到
        System.out.println(file+"--------------------------------------------------");
        return;
      }
      for (File f : files) {
        if (f.isDirectory()) {
          DirectoryNode dn = new DirectoryNode(f.getName());
          
          dn.setNid(UUID.randomUUID().toString());
          dn.setPid(((DirectoryNode)parentNode).getNid());
          
          parentNode.addNode(dn);
          scan(f,dn,ds);
        } else {
          
          boolean isFilter = filter(ds,f.getName());
          
          if(!isFilter&&f.canRead()){
            FileNode node = new FileNode(f.getName());
            System.out.println(f);
            
            String signature = null;
            try {
              FileInputStream in = new FileInputStream(f);
              signature = DigestUtils.md5Hex(in);
            } catch (IOException e1) {
              e1.printStackTrace();
//              return;
            }
            FileInfo info = node.getInfo();
            info.setFileSize(f.length());
            if(f.length()>Constants.LARGE_FILE_SIZE){
              info.setType(Constants.FILE_TYPE_LARGE);
            }
            if(signature==null){
              signature = UUID.randomUUID().toString();
              node.setStatus(Node.STATUS_FAILED);
            }
            info.setSignature(signature);
            info.setName(node.getName());
            info.setPath(parentNode.getPath());
            
            node.setNid(UUID.randomUUID().toString());
              
            node.setPid(parentNode.getNid());
            
            parentNode.addNode(node);
            
            if(ds.getIsOpenLocalBackup() == Constants.IS_OPEN_LOCAL_BACKUP){
              LocalBackupTask task = new LocalBackupTask(ds.getRoot(),ds.getId(), node,ds.getNextVersion().getVersion());
              try {
                LocalBackupQueue.enqueue(task);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
            }
          }
          
        }
      }
    }
  }
  
  /**
   * @author 张建峰
   * @Description: 判断是否过滤
   * @param @param ds 数据源
   * @param @param path 文件路径
   * @param @return
   * @return boolean 
   * @date 2015年9月6日上午11:56:08
   *
   */
  public static boolean filter(DataSource ds,String path){
    boolean isFilter = false;
    String[] filters = {};
    int idx = 0;
    if(ds.getFilterFileSuffix() != null){
      filters = ds.getFilterFileSuffix().split(",");
      idx = path.lastIndexOf(".");
    }
    
    if(ds.getScanType()!=null){
      if(ds.getScanType().equals(Constants.FILTER_SOME)){
        if(idx != -1){
          String suffix = path.substring(idx+1);
          for (int i = 0; i < filters.length; i++) {
            if(filters[i].equals(suffix)){
              isFilter = true;
              break;
            }
          }
        }
      }else if(ds.getScanType().equals(Constants.FILTER_NOT_SOME)){
        if(idx != -1){
          String suffix = path.substring(idx+1);
          for (int i = 0; i < filters.length; i++) {
            if(filters[i].equals(suffix)){
              isFilter = true;
              break;
            }
          }
          isFilter = !isFilter;
        }
      }
    }
    
    return isFilter;
  }
  
  public static void save(VersionTree vt, String dsId, String version) {
    String path = getVersionTreePath(dsId, version);
    File fileDir = new File(path);
    if(!fileDir.getParentFile().exists()){
      fileDir.getParentFile().mkdirs();
    }
    LOG.debug("write version tree {} to {}", dsId, path);
    try {
      VersionTreeSerializerFactory.getSerializer().writeObject(path, vt);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public static VersionTree loadVersionTree(String dsId, String version) {
    LOG.debug("load version tree {}, {}", dsId, version);
    VersionTree vt = null;
    String path = getVersionTreePath(dsId, version);
    try {
      vt = VersionTreeSerializerFactory.getSerializer().readObject(path);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return vt;
  }

  public static String getVersionTreePath(String dsId, String version) {
    return FileUtil.getVersionFilePath(dsId, version);
  }

  public static List<Node> getChangeList(VersionTree prev, VersionTree current) {
    if (prev != null) {
      prev.merge(current);
      return prev.takeChangeList();
    }
    if (current != null) {
      return current.takeNodeList();
    }
    return new ArrayList<Node>();
  }

  /** 首先看版本树目录中是否存在该版本文件，不存在从压缩目录寻找，还找不到则从服务端下载，下载后解压构建版本树。 */
  public static VersionTree getVersionTree(String dsId, String version) {
    LOG.debug("get version tree {}, {}", dsId, version);
    String versionPath = FileUtil.getVersionFilePath(dsId, version);
    String zipPath = FileUtil.getZipVersionFilePath(dsId, version) + ".zip";
    File f = new File(versionPath);
    if (!f.exists()) {
      f = new File(zipPath);
      if (!f.exists()) {
        TransportUtil.downloadVersionTree(dsId, version);
        File zip = new File(FileUtil.getZipVersionFilePath(dsId, version));
        zip.renameTo(new File(zipPath));
      }
      
      new ZipUtil().unZip(zipPath, FileUtil.getDataSourcePath(dsId) + File.separator + FileUtil.PATH_VERSION);
    }

    return VersionTreeUtil.loadVersionTree(dsId, version);
  }
}
